package microcredit.gui.util;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.AbstractButton;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.JTextComponent;

import microcredit.gui.table.BeanTable;

import org.jdesktop.swingx.JXDatePicker;

public class UIStateCapture {

	private Component c;
	private List<ActionListener> actionListeners = new ArrayList<ActionListener>();
	
	public UIStateCapture(Component c) {
		this.c = c;
		UIUtil.iterate(c, new ComponentIterator<Void>() {
			@Override
			public boolean iterateChildren(Component c) {
				return !(c instanceof JXDatePicker);
			}
			@Override
			public Void iterate(Component c) {
				enable(c);
				return null;
			}
		});
	}
	
	public void addActionListener(ActionListener l) {
		actionListeners.add(l);
	}
	
	public void removeActionListener(ActionListener l) {
		actionListeners.remove(l);
	}
	
	private void enable(Component c) {
		if (c instanceof JTextComponent) {
			((JTextComponent) c).getDocument().addDocumentListener(documentListener);
		} else if (c instanceof AbstractButton) {
			if (!(c instanceof JButton)) {
				((AbstractButton) c).addActionListener(actionListener);
			}
		} else if (c instanceof JComboBox) {
			((JComboBox) c).addItemListener(itemListener);
		} else if (c instanceof BeanTable<?>) {
			((BeanTable<?>)c).addChangeListener(changeListener);
		} else if (c instanceof JXDatePicker) {
			((JXDatePicker) c).addActionListener(actionListener);
		}
	}
	
	private void disable(Component c) {
		if (c instanceof JTextComponent) {
			((JTextComponent) c).getDocument().removeDocumentListener(documentListener);
		} else if (c instanceof AbstractButton) {
			if (!(c instanceof JButton)) {
				((AbstractButton) c).removeActionListener(actionListener);
			}
		} else if (c instanceof JComboBox) {
			((JComboBox) c).removeItemListener(itemListener);
		} else if (c instanceof BeanTable<?>) {
			((BeanTable<?>)c).removeChangeListener(changeListener);
		} else if (c instanceof JXDatePicker) {
			((JXDatePicker) c).removeActionListener(actionListener);
		}
	}
	
	private void change() {
		for (ActionListener listener : actionListeners) {
			listener.actionPerformed(null);
		}
	}
	
	public static UIStateCapture capture(Component c) {
		return new UIStateCapture(c);
	}
	
	public static void destroy(final UIStateCapture capture) {
		UIUtil.iterate(capture.c, new ComponentIterator<Void>() {
			@Override
			public boolean iterateChildren(Component c) {
				return true;
			}
			@Override
			public Void iterate(Component c) {
				capture.disable(c);
				return null;
			}
		});
	}
	
	private ActionListener actionListener = new ActionListener() {
		@Override
		public void actionPerformed(ActionEvent e) {
			change();
		}
	};
	private DocumentListener documentListener = new DocumentListener() {
		@Override
		public void removeUpdate(DocumentEvent e) {
			change();
		}
		@Override
		public void insertUpdate(DocumentEvent e) {
			change();
		}
		@Override
		public void changedUpdate(DocumentEvent e) {
			change();
		}
	};
	
	private ItemListener itemListener = new ItemListener() {
		@Override
		public void itemStateChanged(ItemEvent e) {
			change();
		}
	};
	
	private BeanTable.ChangeListener changeListener = new BeanTable.ChangeListener() {
		public void changed() {
			change();
		};
	};
	
    
}
